package cn.zuo.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author 白白旧维
 * @Date 2021/7/7 11:13
 */
public class AES {

    public static List<Byte> encrypt_ECB(String msg,String seed){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");//创建AES的key生产者
            keyGenerator.init(128,new SecureRandom(seed.getBytes()));//利用seed作为随机数初始化出
            SecretKey secretKey = keyGenerator.generateKey();//根据seed，生成一个密钥
            byte[] encodeFormat = secretKey.getEncoded();//返回基本编码格式的密钥，如果此密钥不支持编码，则返回null
            SecretKeySpec key = new SecretKeySpec(encodeFormat, "AES");//转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//创建密码器 //"算法/模式/补码方式"
            byte[] msgBytes = msg.getBytes("utf-8");//
            cipher.init(Cipher.ENCRYPT_MODE,key);//初始化为加密模式的密码器
            byte[] finalBytes = cipher.doFinal(msgBytes);//加密
            List<Byte> bytes = new ArrayList<>();
            for(int i=0;i<finalBytes.length;i++){
                bytes.add(finalBytes[i]);
            }
            return bytes;
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    public static String decrypt_ECB(List<Byte> msgBytes,String seed) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");//创建AES的Key生产者
            keyGenerator.init(128, new SecureRandom(seed.getBytes()));
            SecretKey secretKey = keyGenerator.generateKey();//根据seed，生成一个密钥
            byte[] encodeFormat = secretKey.getEncoded();//返回基本编码格式的密钥
            SecretKeySpec key = new SecretKeySpec(encodeFormat, "AES");//转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//创建密码器
            cipher.init(Cipher.DECRYPT_MODE, key);//初始化为解密模式的密码器
            byte[] bytes = new byte[msgBytes.size()];
            for (int i = 0; i < msgBytes.size(); i++) {
                bytes[i] = msgBytes.get(i);
            }
            return new String(cipher.doFinal(bytes));//解密
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }


    public static List<Byte> encrypt_CBC(String msg,String seed){
        return encrypt_mode(msg,seed,"CBC");
    }

    public static String decrypt_CBC(List<Byte> msgBytes,String seed){
        return decrypt_mode(msgBytes,seed,"CBC");
    }

    public static List<Byte> encrypt_CTR(String msg,String seed){
        return encrypt_mode(msg,seed,"CTR");
    }

    public static String decrypt_CTR(List<Byte> msgBytes,String seed){
        return decrypt_mode(msgBytes,seed,"CTR");
    }

    public static List<Byte> encrypt_CFB(String msg,String seed){
        return encrypt_mode(msg,seed,"CFB");
    }

    public static String decrypt_CFB(List<Byte> msgBytes,String seed){
        return decrypt_mode(msgBytes,seed,"CFB");
    }

    public static List<Byte> encrypt_OFB(String msg,String seed){
        return encrypt_mode(msg,seed,"OFB");
    }

    public static String decrypt_OFB(List<Byte> msgBytes,String seed){
        return decrypt_mode(msgBytes,seed,"OFB");
    }

    private static List<Byte> encrypt_mode(String msg,String seed,String mode){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");//创建AES的key生产者
            keyGenerator.init(128,new SecureRandom(seed.getBytes()));//利用seed作为随机数初始化出
            SecretKey secretKey = keyGenerator.generateKey();//根据seed，生成一个密钥
            byte[] encodeFormat = secretKey.getEncoded();//返回基本编码格式的密钥，如果此密钥不支持编码，则返回null
            SecretKeySpec key = new SecretKeySpec(encodeFormat, "AES");//转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES/"+mode+"/PKCS5Padding");//创建密码器 //"算法/模式/补码方式"
            byte[] msgBytes = msg.getBytes("utf-8");//
            byte[] kk = new byte[16];
            for(int i=0;i<16;i++){
                kk[i] = seed.getBytes()[i];
            }
            IvParameterSpec iv = new IvParameterSpec(kk);//kk必须是16个
            cipher.init(Cipher.ENCRYPT_MODE,key,iv);//初始化为加密模式的密码器
            byte[] finalBytes = cipher.doFinal(msgBytes);//加密
            List<Byte> bytes = new ArrayList<>();
            for(int i=0;i<finalBytes.length;i++){
                bytes.add(finalBytes[i]);
            }
            return bytes;//加密
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    private static String decrypt_mode(List<Byte> msgBytes,String seed,String mode){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");//创建AES的Key生产者
            keyGenerator.init(128,new SecureRandom(seed.getBytes()));
            SecretKey secretKey = keyGenerator.generateKey();//根据seed，生成一个密钥
            byte[] encodeFormat = secretKey.getEncoded();//返回基本编码格式的密钥
            SecretKeySpec key = new SecretKeySpec(encodeFormat, "AES");//转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES/"+mode+"/PKCS5Padding");//创建密码器
            byte[] kk = new byte[16];
            for(int i=0;i<16;i++){
                kk[i] = seed.getBytes()[i];
            }
            IvParameterSpec iv = new IvParameterSpec(kk);
            cipher.init(Cipher.DECRYPT_MODE,key,iv);//初始化为解密模式的密码器
            byte[] bytes = new byte[msgBytes.size()];
            for (int i = 0; i < msgBytes.size(); i++) {
                bytes[i] = msgBytes.get(i);
            }
            return new String(cipher.doFinal(bytes));//解密
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }


}
